package ${projectDomain}.adapter;

import java.util.List;

import org.apache.ibatis.session.ResultHandler;
import org.springframework.beans.factory.annotation.Autowired;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.validate.IValidateAdapter;
import ${projectDomain}.mapper.BaseSearchMapper;
import ${projectDomain}.pojo.dao.BaseDo;
import ${projectDomain}.pojo.dao.PageDo;
import ${projectDomain}.pojo.dao.SearchDo;
import ${projectDomain}.pojo.dao.SingleDo;
import ${projectDomain}.pojo.dao.sql.Sql;
import ${projectDomain}.pojo.vo.page.PageVo;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;

@Api(value="管理层查询公共操作类，架构规定，service只能调用adapter，adapter为公共业务操作块", author="unswift", date="2023-04-16", version="1.0.0")
public abstract class BaseSearchAdapter extends AutoSqlAdapter{

	@Autowired
	@ApiField("数据验证业务对象")
	protected IValidateAdapter validateAdapter;
	
	@ApiMethod(value="获取当前管理层对应的Mybatis Mapper", returns=@ApiField("获取当前管理层对应的Mybatis Mapper"))
	public abstract BaseSearchMapper getMapper();

	@ApiMethod(value="获取当前管理层对应的模块key", returns=@ApiField("模块key"))
	public abstract String getModule();
	
	@ApiMethod(value="根据主键id在数据库总查询对应实体，此So对象的id值必须存在，sql对象可控制查询的具体字段", params=@ApiField("查询的so对象"), returns=@ApiField("实体对象"))
	public <T extends SingleDo, V extends BaseDo> V findSingle(T search){
		ExceptionUtils.trueException(ObjectUtils.isEmpty(ClassUtils.get(search, "id")) && (ObjectUtils.isEmpty(search.getSql()) || ObjectUtils.isEmpty(search.getSql().getWhereList())), "search.pk.not.empty");//id不能未空
		return getMapper().findSingle(search);
	}
	
	@ApiMethod(value="根据实体查询条件查询符合条件的数量", params={@ApiField("实体对象")}, returns=@ApiField("数量"))
	public <T extends SearchDo> int findCount(T search){
		if(validateAdapter.entityFieldEmpty(search)){//不允许全表查询，必须存在查询条件
			throw ExceptionUtils.message("search.condition.not.empty");
		}
		return getMapper().findCount(search);
	}
	
	@ApiMethod(value="根据实体查询条件查询符合条件的实体列表", params={@ApiField("实体对象")}, returns=@ApiField("实体列表对象"))
	public <T extends SearchDo, V extends BaseDo> List<V> findList(T search){
		if(validateAdapter.entityFieldEmpty(search)){//不允许全表查询，必须存在查询条件
			throw ExceptionUtils.message("search.condition.not.empty");
		}
		if(search instanceof PageDo){//如果是PageDo，表示可能要分页
			PageDo pageSearch=(PageDo)search;
			if(ObjectUtils.isNotEmpty(pageSearch.getFirstSize()) && ObjectUtils.isNotEmpty(pageSearch.getPageSize())){
				Sql sql=pageSearch.getSql();
				if(ObjectUtils.isEmpty(sql)){
					sql=Sql.createSql(pageSearch.getFirstSize(), pageSearch.getPageSize());
					pageSearch.setSql(sql);
				}else{
					//PageDo的分页优先考虑，如果sql本身就存在分页信息了，则会覆盖
					sql.setFirstSize(pageSearch.getFirstSize());
					sql.setPageSize(pageSearch.getPageSize());
				}
			}
		}
		return getMapper().findList(search);
	}
	
	@ApiMethod(value="根据Page对象查询符合条件的Page数据对象", params={@ApiField("page对象")}, returns=@ApiField("Page数据对象"))
	public <T extends PageDo, V extends BaseDo> PageVo<V> findPageList(T search){
		PageVo<V> page=new PageVo<V>(search.getCurrPage(), search.getPageSize());
		int count=this.findCount(search);
		page.setTotalSize(count);
		if(count>0){
			page.setDataList(this.findList(search));
		}
		return page;
	}
	
	@ApiMethod(value="根据so实体查询游标数据对象", params={@ApiField("查询条件"), @ApiField("MyBatis流式查询对象，用于接收数据")})
	public <T extends SearchDo, V extends BaseDo> void findBigData(T search, ResultHandler<V> out){
		this.getMapper().findBigData(search, out);
	}
	
}
